package chen.web.forum;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.util.Assert;

import chen.web.DataSourceProvider;
import chen.web.forum.SubjectCondition.SubjectType;
import chen.web.forum.Subject.TopRank;
import chen.web.user.Account;
import chen.web.util.DateInt;
import chen.web.widget.WidgetManagerFactory;

public class TopicManagerImpl implements TopicManager {
	
	private static SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(DataSourceProvider.getDataSource());
	
	private CategoryManager cm = null;
	private SubjectManager sm = null;
	private ReplyManager rm = null;
	public TopicManagerImpl(ForumAccountLoader fal, CategoryManager cm, WidgetManagerFactory wmf){
		this.cm = cm;
		this.sm = new SubjectManager(fal, cm, wmf);
		this.rm = new ReplyManager(fal, sm);
	}
	
	private static class IntRowMapper implements RowMapper<Integer>{
		@Override
		public Integer mapRow(ResultSet rs, int i) throws SQLException {
			// TODO Auto-generated method stub
			return rs.getInt(1);
		}
	}
	
	@Override
	public List<TopicInfo> getTopicInfoList(SubjectCondition condition, int beginOffset, int count) {
		// TODO Auto-generated method stub
		Assert.notNull(condition);
		StringBuilder sql1 = new StringBuilder()
							.append("select sub_id from web_subject")
							.append(condition.toSql())
							.append("limit ?, ?");
		List<Integer> ids = simpleJdbcTemplate.query(sql1.toString(), new IntRowMapper(), beginOffset, count);
		//结果集为空
		if(ids.size() == 0){
			return new ArrayList<TopicInfo>(0);
		}
		
		StringBuilder sql2 = new StringBuilder()
							.append("select sub_id, sub_title, sub_viewCount, sub_replyCount, sub_authorId, sub_authorNickname, sub_lastReplyDate, sub_lastReplierId, sub_lastReplierNickname, sub_good, sub_top, sub_ip, sub_flag, sub_widgetType, cat_id from web_subject where sub_id in (");
		for(int id : ids){
			sql2.append(id).append(',');
		}
		sql2.deleteCharAt(sql2.length()-1);
		sql2.append(')');
		
		List<TopicInfo> list = simpleJdbcTemplate.query(sql2.toString(), new TopicInfoRowMapper());
		for(TopicInfo topic : list){
			topic.setCategory(cm.get(topic.getCategory().getId()));
		}
		
		//置顶贴子需要根据置顶等级排序
		if(condition.getType() == SubjectType.top){
			TopicInfo[] items = list.toArray(new TopicInfo[list.size()]);
			for(int i=0; i<items.length; i++){
				TopicInfo item1 = items[i];
				Subject.TopRank rank1 = Subject.getTopRank(item1.getFlag());
				for(int j=i+1; j<items.length; j++){
					TopicInfo item2 = items[j];
					Subject.TopRank rank2 = Subject.getTopRank(item2.getFlag());
					if(rank2.ordinal() > rank1.ordinal()){
						items[i] = item2;
						items[j] = item1;
					}
				}
			}
			list = Arrays.asList(items);
		} else {	//非置顶贴子根据id顺序排序
			//按照id顺序排序
			int index = 0;
			for(int id : ids){
				for(int i=0; i<list.size(); i++){
					TopicInfo info = list.get(i);
					if(info.getId() == id){
						TopicInfo temp = list.get(index);
						list.set(index, info);
						list.set(i, temp);
						++ index;
					}
				}
			}
		}
		return list;
	}

	
	public static final class TopicInfoRowMapper implements RowMapper<TopicInfo>{

		@Override
		public TopicInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
			// TODO Auto-generated method stub
			TopicInfo info = new TopicInfo();
			info.setId(rs.getInt("sub_id"));
			info.setAuthorId(rs.getInt("sub_authorId"));
			info.setAuthorNickame(rs.getString("sub_authorNickname"));
			info.setLastReplierId(rs.getInt("sub_lastReplierId"));
			info.setLastReplierNickname(rs.getString("sub_lastReplierNickname"));
			info.setLastReplyDate(DateInt.transform(rs.getInt("sub_lastReplyDate")));
			info.setReplyCount(rs.getInt("sub_replyCount"));
			info.setTitle(rs.getString("sub_title"));
			info.setIp(rs.getString("sub_ip"));
			info.setViewCount(rs.getInt("sub_viewCount"));
			info.setDigest(rs.getBoolean("sub_good"));
			info.setTop(rs.getBoolean("sub_top"));
			info.setFlag(rs.getInt("sub_flag"));
			Category category = new Category(rs.getInt("cat_id"));
			int widgetType = rs.getInt("sub_widgetType");
			info.setWidgetType(widgetType);
			info.setCategory(category);
			return info;
		}
	}
	
	private static final String SQL_21 = "delete from web_subject_reply where sub_id = ?";
	@Override
	public void delete(Subject subject) {
		// TODO Auto-generated method stub
		sm.delete(subject);
		simpleJdbcTemplate.update(SQL_21, subject.getId());
	}

	public void delete(Reply reply) {
		// TODO Auto-generated method stub
		rm.delete(reply);
	}

	@Override
	public Reply getReply(int replyId) {
		// TODO Auto-generated method stub
		return rm.getReply(replyId);
	}

	@Override
	public Subject getSubject(int subjectId) {
		// TODO Auto-generated method stub
		return sm.getSubject(subjectId);
	}

	@Override
	public void increaseViewCount(Subject subject) {
		// TODO Auto-generated method stub
		sm.increaseViewCount(subject);
	}
	
	@Override
	public void update(Subject subject) {
		sm.update(subject);
	}

	@Override
	public void update(Reply reply) {
		// TODO Auto-generated method stub
		rm.update(reply);
	}

	@Override
	public Subject post(final Subject subject) throws NotLowestException {
		// TODO Auto-generated method stub
		return sm.post(subject);
	}

	@Override
	public Reply post(Reply reply) {
		// TODO Auto-generated method stub
		Reply re = rm.post(reply);
		return re;
	}

	@Override
	public List<Object> search(String keywords) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public int replyAmount(Account acc) {
		// TODO Auto-generated method stub
		return rm.replyAmount(acc);
	}

	@Override
	public int replyPositionInTopic(Reply reply) {
		// TODO Auto-generated method stub
		return rm.replyOrderInTopic(reply);
	}
	
	@Override
	public int totalSubject(SubjectCondition condition) {
		// TODO Auto-generated method stub
		return sm.totalSubject(condition);
	}
	
/*	@Override
	public int totalReply(Category category, boolean containsChildren) {
		return rm.totalReply(category, containsChildren);
	}*/

	@Override
	public Subject setDigest(Subject subject, boolean digest) {
		// TODO Auto-generated method stub
		subject.setDigest(digest);
		sm.update(subject);
		return subject;
	}

	@Override
	public Subject setTop(Subject subject, TopRank rank) {
		// TODO Auto-generated method stub
		subject.setTop(true);
		subject.setTopRank(rank);
		sm.update(subject);
		return subject;
	}

	@Override
	public Subject cancelTop(Subject subject) {
		// TODO Auto-generated method stub
		subject.setTop(false);
		sm.update(subject);
		return subject;
	}

	@Override
	public Reply hideReplyContent(Reply reply, boolean hide) {
		// TODO Auto-generated method stub
		reply.setHide(hide);
		rm.update(reply);
		return reply;
	}

	@Override
	public Subject hideSubjectContent(Subject subject, boolean hide) {
		// TODO Auto-generated method stub
		subject.setHide(hide);
		sm.update(subject);
		return subject;
	}

	@Override
	public Subject forbidReply(Subject subject, boolean forbid) {
		// TODO Auto-generated method stub
		subject.setForbidReply(forbid);
		sm.update(subject);
		return subject;
	}

	@Override
	public Subject move(Subject subject, Category category) throws NotLowestException {
		// TODO Auto-generated method stub
		if(category.getChildren().size()>0){
			throw new NotLowestException();
		}
		subject.setCategory(category);
		sm.update(subject);
		return subject;
	}

	private static final String SQL_1 = "select sub_id, sub_title, sub_viewCount, sub_replyCount, sub_authorId, sub_authorNickname, sub_lastReplyDate, sub_lastReplierId, sub_lastReplierNickname, sub_good, sub_top, sub_ip, sub_flag, sub_widgetType, cat_id from web_subject right join (select distinct sub_id as sid from web_subject_reply where reply_authorId = ? order by reply_dateline desc limit ?,?)t on web_subject.sub_id=t.sid";
	@Override
	public List<TopicInfo> getRepliedTopicInfoList(Account account,
			int beginOffset, int count) {
		// TODO Auto-generated method stub
		List<TopicInfo> list = simpleJdbcTemplate.query(SQL_1, new TopicInfoRowMapper(), account.getId(), beginOffset, count);
		for(TopicInfo topic : list){
			topic.setCategory(cm.get(topic.getCategory().getId()));
		}
		return list;
	}

/*	private static final String SQL_2 = "select count(distinct sub_id) from web_subject_reply where reply_authorId = ?";
	@Override
	public int totalRepliedTopic(Account account) {
		// TODO Auto-generated method stub
		int count = simpleJdbcTemplate.queryForInt(SQL_2, account.getId());
		return count;
	}
*/

	@Override
	public Subject restore(Subject subject) {
		// TODO Auto-generated method stub
		subject.setFakeDelete(false);
		sm.update(subject);
		return subject;
	}

	@Override
	public Reply restore(Reply reply) {
		// TODO Auto-generated method stub
		reply.setFakeDelete(false);
		rm.update(reply);
		return reply;
	}

	@Override
	public Reply checked(Reply reply) {
		// TODO Auto-generated method stub
		reply.setNeedChecking(false);
		rm.update(reply);
		return reply;
	}

	@Override
	public Subject checked(Subject subject) {
		// TODO Auto-generated method stub
		subject.setNeedChecking(false);
		sm.update(subject);
		return subject;
	}

	@Override
	public List<Reply> getReplyList(ReplyCondition condition, int beginOffset,
			int count) {
		// TODO Auto-generated method stub
		return rm.getReplyList(condition, beginOffset, count);
	}

	@Override
	public int totalReply(ReplyCondition condition) {
		// TODO Auto-generated method stub
		return rm.totalReply(condition);
	}
	
	@Override
	public boolean safeDelete(Subject subject){
		if(subject.getCategory().isRecycle() && !subject.isNeedChecking()){
			subject.setFakeDelete(true);
			sm.update(subject);
			return false;
		} else {
			this.delete(subject);	
			return true;
		}
	}
	
	@Override
	public boolean safeDelete(Reply reply){
		if(reply.getBelongSubject().getCategory().isRecycle() && !reply.isNeedChecking()){
			reply.setFakeDelete(true);
			rm.update(reply);
			return false;
		} else {
			this.delete(reply);
			return true;
		}
	}

}
